home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 009a / comm_c_3.zip / COMM.C next >
C/C++ Source or Header  |  1993-05-21  |  17KB  |  420 lines

  1. #define DEBUG                              /* comment me to eliminate main() */
  2.  
  3. /*     Last modification by Rick Wagner, May 21, 1993.
  4.  *
  5.  *     - Changed some declarations for compilation under MS QC2.5
  6.  *     - Changed some function names for compilation under MS QC2.5
  7.  *     - Changed delay()
  8.  *     -
  9.  *     Needs: A more specific interuppt mask, disable() may cause
  10.  *            problems (e.g. missed kbhits).
  11.  */
  12.  
  13. /*     Last modification by Al Sharpe, April 28, 1990.
  14.  *
  15.  *     - corrected comm_close() to drop RTS and DTR, not just DTR.
  16.  *     - correct flsh_dtr( ) to drop only DTR and leave RTS active.
  17.  *     - flsh_dtr( ) duration extented to 1/2 second.
  18.  *     - correct all bugs in function main( ) so test program will work.
  19.  *     - removed global CARRIER as it was redundant.
  20.  *     - conio.h added for cprintf( ) function.
  21.  */
  22.  
  23. /*    Modification, to support comm ports 3 & 4
  24.  *       Al Sharpe, June 7, 1989
  25.  *    Minor changes added to handle DTR on port close.
  26.  *
  27.  *    New function added :
  28.  *      flsh_dtr( )   -  drops DTR for 200 milliseconds
  29.  *
  30.  *    Old function modified :
  31.  *      comm_getc( unsigned seconds )   -  (1) gets a char from input buffer
  32.  *                                             with timeout
  33.  *                                         (2) if a key is pressed a Timeout
  34.  *                                             is returned
  35.  */
  36.  
  37. /*    Modification, to support other compiler(s):
  38.  *       Pete Gontier, July 20th, 1988
  39.  *    This code is no longer portable to the UNIX systems mentioned.
  40.  *    The function names were in accordance with the TT teletype conventions,
  41.  *    and I couldn't stand for it. So sue me.
  42.  */
  43.  
  44. /*    From CompuServe's BPROGB Borland Int'l forum
  45.  *
  46.  *    #:  11879 S4/Turbo C
  47.  *        02-Jun-88  18:54:50
  48.  *    Sb: #11817-VT100
  49.  *    Fm: Jerry Joplin 70441,2627
  50.  *    To: Pete Gontier 72261,1754 (X)
  51.  *
  52.  *    Pete, here are the communication ISR's I've been using.   Hope these
  53.  *    don't overflow the message data base for BPROGB.  :-)
  54.  *    I think all is included to set up COM1/COM2 for receiver interrupts.
  55.  *
  56.  *    Also, these are straight ports from routines in MSKERMIT 2.30 and CKERMIT
  57.  *    for UNIX, which are public domain but copyrighted (c) by Columbia
  58.  *    University.
  59.  */
  60.  
  61.  
  62. #include <stdlib.h>
  63. #include <dos.h>
  64. #include <bios.h>
  65. #include <conio.h>
  66. #include <time.h>
  67. #include "comm.h"                                /* comm prototypes */
  68.  
  69. #define TCICOMM                                  /* avoid extern declaration in... */
  70.                  
  71. #define MDMDAT1 0x03F8                           /* Address of modem port 1 data */
  72. #define MDMSTS1 0x03FD                           /* Address of modem port 1 status  */
  73. #define MDMCOM1 0x03FB                           /* Address of modem port 1 command */
  74. #define MDMDAT2 0x02F8                           /* Address of modem port 2 data */
  75. #define MDMSTS2 0x02FD                           /* Address of modem port 2 status */
  76. #define MDMCOM2 0x02FB                           /* Address of modem port 2 command */
  77. #define MDMDAT3 0x03E8                           /* Address of modem port 3 data */
  78. #define MDMSTS3 0x03ED                           /* Address of modem port 3 status  */
  79. #define MDMCOM3 0x03EB                           /* Address of modem port 3 command */
  80. #define MDMDAT4 0x02E8                           /* Address of modem port 4 data */
  81. #define MDMSTS4 0x02ED                           /* Address of modem port 4 status */
  82. #define MDMCOM4 0x02EB                           /* Address of modem port 4 command */
  83. #define MDMINTV 0x000C                           /* Com 1 & 3 interrupt vector */
  84. #define MDINTV2 0x000B                           /* Com 2 & 4 interrupt vector */
  85. #define MDMINTO 0x0EF                            /* Mask to enable IRQ3 for port 1 & 3 */
  86. #define MDINTO2 0x0F7                            /* Mask to enable IRQ4 for port 2 & 4 */
  87. #define MDMINTC 0x010                            /* Mask to Disable IRQ4 for port 1 & 3 */
  88. #define MDINTC2 0x008                            /* Mask to Disable IRQ3 for port 2 & 4 */
  89. #define INTCONT 0x0021                           /* 8259 interrupt controller ICW2-3 */
  90. #define INTCON1 0x0020                           /* Address of 8259 ICW1 */
  91. #define CBS     2048                             /* Communications port buffer size */
  92. #define XOFF    0x13                             /* XON/XOFF */
  93. #define XON     0x11
  94. #define CARRIER_ON  0x80                         /* Return value for carrier detect */
  95.  
  96.  
  97. /** globals not externally accessible ***************************************/
  98.  
  99. static int    MODEM_STAT;                        /* 8250 modem status register */
  100. static int    dat8250;                           /* 8250 data register */
  101. static int    stat8250;                          /* 8250 line-status register */
  102. static int    com8250;                           /* 8250 line-control register */
  103. static char   en8259;                            /* 8259 IRQ enable mask */
  104. static char   dis8259;                           /* 8259 IRQ disable mask */
  105. static unsigned int intv;                        /* interrupt number to usurp */
  106.  
  107. static char   buffer[CBS];                       /* Communications circular buffer */
  108. static char   *inptr;                            /* input address of circular buffer */
  109. static char   *outptr;                           /* output address of circular buffer */
  110. static int    c_in_buf = 0;                      /* count of characters received */
  111. static int    xoffpt;                            /* amount of buffer that forces XOFF */
  112. static int    xonpt;                             /* amount of buffer that unXOFFs */
  113.  
  114. static void (_interrupt _far *oldvec) ( );       /* vector of previous comm interrupt */
  115. int xonxoff = 0;                                 /* auto xon/xoff support flag */
  116. int xofsnt  = 0;                                 /* XOFF transmitted flag */
  117. int xofrcv  = 0;                                 /* XOFF received flag */
  118.  
  119. void _interrupt _far serint ( void ) 
  120. {                                                /* ISR to receive character */
  121.    *inptr++ = (char) inp ( dat8250 );            /* Store character in buffer */
  122.    c_in_buf++;                                   /* and increment count */
  123.    if ( xonxoff ) 
  124.    {                                             /* if xon/xoff auto-support is on */
  125.       if ( c_in_buf > xoffpt && ! xofsnt ) 
  126.       {                                          /* then if buf nearly full */
  127.      comm_putc ( XOFF );                     /* send an XOFF */
  128.      xofsnt = 1;                             /* and say so */
  129.       }
  130.    }
  131.    _disable ( );                                 /* ints off for ptr change */
  132.    if ( inptr == &buffer[CBS] )            
  133.    {                                             /* Set buffer input pointer */
  134.       inptr = buffer;
  135.    }
  136.    _enable ( );
  137.    outp ( 0x20, 0x20 );                          /* Generic EOI to 8259 */
  138. }
  139.  
  140.  
  141. void comm_close ( void ) 
  142. {                                                /* restore previous settings of 8259 */
  143.  
  144.     outp ( com8250 + 1, 0x08 );                  /* Drop OUT2 */
  145.     outp ( com8250 + 1, 0x00 );                  /* Drop DTR and RTS /*
  146.     outp ( INTCONT, dis8259 | inp ( INTCONT ) );
  147.                          /* Disable com interrupt at 8259 */
  148.     _dos_setvect ( intv, oldvec );               /* Reset original interrupt vector */
  149. }
  150.  
  151. void dobaud ( unsigned baudrate )                /* parses baud integer to mask, */
  152. {                                                /* re-inits port accordingly */
  153.    unsigned char portval;
  154.    unsigned char blo, bhi;
  155.    switch  ( baudrate )                          /* Baud rate LSB's and MSB's */
  156.    {
  157.        case 50:     bhi = 0x9;  blo = 0x00;  break;
  158.        case 75:     bhi = 0x6;  blo = 0x00;  break;
  159.        case 110:    bhi = 0x4;  blo = 0x17;  break;
  160.        case 150:    bhi = 0x3;  blo = 0x00;  break;
  161.        case 300:    bhi = 0x1;  blo = 0x80;  break;
  162.        case 600:    bhi = 0x0;  blo = 0xC0;  break;
  163.        case 1200:   bhi = 0x0;  blo = 0x60;  break;
  164.        case 1800:   bhi = 0x0;  blo = 0x40;  break;
  165.        case 2000:   bhi = 0x0;  blo = 0x3A;  break;
  166.        case 2400:   bhi = 0x0;  blo = 0x30;  break;
  167.        case 4800:   bhi = 0x0;  blo = 0x18;  break;
  168.        case 9600:   bhi = 0x0;  blo = 0x0C;  break;
  169.        case 19200:  bhi = 0x0;  blo = 0x06;  break;
  170.        default:
  171.        return;
  172.    }
  173.    portval = (unsigned char) inp ( com8250 );    /* read Line-Control Reg val */
  174.    outp ( com8250, portval | 0x80 );             /* set high bit for baud init */
  175.    outp ( dat8250, blo );                        /* Send LSB for baud rate */
  176.    outp ( dat8250 + 1, bhi );                    /* Send MSB for baud rate */
  177.    outp ( com8250, portval );                    /* Reset initial value at LCR */
  178. }
  179.  
  180.  
  181. /* installs comm interrupts */
  182.  
  183. int comm_open ( int portid, unsigned speed )
  184. {
  185.    int be = _bios_equiplist ( );                 /* to get # installed serial ports */
  186.    be <<= 4;                                     /* shift-wrap high bits off */
  187.    be >>= 13;                                    /* shift down to low bits */
  188.    if ( be >= portid || portid >= 3) 
  189.    {
  190.       if ( portid == 1 ) 
  191.       {
  192.       dat8250  = MDMDAT1;
  193.       stat8250 = MDMSTS1;
  194.       com8250  = MDMCOM1;
  195.       dis8259  = MDMINTC;
  196.       en8259   = MDMINTO;
  197.       intv = MDMINTV;
  198.       }
  199.       if ( portid == 2 ) 
  200.       {
  201.       dat8250  = MDMDAT2;
  202.       stat8250 = MDMSTS2;
  203.       com8250  = MDMCOM2;
  204.       dis8259  = MDINTC2;
  205.       en8259   = MDINTO2;
  206.       intv = MDINTV2;
  207.       }
  208.       if ( portid == 3 )                         /* Ports 3 & 4 cannot be checked */
  209.       {                                          /* with biosquip( ) */
  210.       dat8250  = MDMDAT3;                        
  211.       stat8250 = MDMSTS3;
  212.       com8250  = MDMCOM3;
  213.       dis8259  = MDMINTC;
  214.       en8259   = MDMINTO;
  215.       intv = MDMINTV;
  216.       }
  217.       if ( portid == 4 ) 
  218.       {
  219.       dat8250  = MDMDAT4;
  220.       stat8250 = MDMSTS4;
  221.       com8250  = MDMCOM4;
  222.       dis8259  = MDINTC2;
  223.       en8259   = MDINTO2;
  224.       intv = MDINTV2;
  225.       }
  226.       if (portid <= 0 && portid >= 5)
  227.       {
  228.      return ( 0 );
  229.       }
  230.  
  231.       MODEM_STAT = dat8250 + 6;                  /* Define Modem Status Register */
  232.       dobaud ( speed );                          /* set baud */
  233.       inptr = outptr = buffer;                   /* set circular buffer values */
  234.       c_in_buf = 0;
  235.       oldvec = _dos_getvect ( intv );            /* Save old int vector */
  236.       _dos_setvect  ( intv, serint );            /* Set up SERINT as com ISR */
  237.       outp ( com8250,     0x3 );                 /* 8 bits no parity */
  238.       outp ( com8250 + 1, 0xb );                 /* Assert OUT2, RTS, and DTR */
  239.       inp  ( dat8250 );
  240.       outp ( dat8250 + 1, 0x1 );                 /* Receiver-Data-Ready int */
  241.       outp ( INTCONT, en8259 & inp ( INTCONT ) );
  242.                          /* Enable 8259 interrupts */
  243.       xoffpt = CBS - 128;                        /* chars in buff to send XOFF */
  244.       xonpt  = CBS - xoffpt;                     /* chars in buff to send XON */
  245.    }                                             /* END of if(be >= portid || portid >= 3) */
  246.    else
  247.    {
  248.       be = 0;
  249.    }
  250.    return ( be );
  251. }
  252.  
  253.  
  254. int comm_avail ( )                               /* returns # characters available in buffer */
  255. {
  256.     return ( c_in_buf );
  257. }
  258.  
  259.  
  260. void comm_putc ( unsigned char c )               /* sends char out port */
  261. {
  262.     while ( ( inp ( stat8250 ) & 0x20 ) == 0 );  /* Wait til transmitter is ready */
  263.     outp ( dat8250, c );                         /* then send it */
  264. }
  265.  
  266.  
  267. int comm_getc ( unsigned seconds )               /* gets char from buffer */
  268. {
  269.     int c;
  270.     long get_tm, end_tm;
  271.     register char * ptr;
  272.  
  273.     if ( c_in_buf < xonpt && xofsnt )            /* Check if we need to send */
  274.     {
  275.        xofsnt = 0;                               /* an XON to the host after */
  276.        comm_putc ( XON );                        /* we had to send an XOFF */
  277.     }
  278.  
  279.     _bios_timeofday(_TIME_GETCLOCK,&get_tm);     /* If character not ready */
  280.     end_tm = get_tm + (18 * seconds);            /* then wait til one is   */
  281.                          /* or return TIMEOUT */
  282.     do 
  283.     {
  284.     if(kbhit()) 
  285.     {                                        /* If key pressed, Timeout */
  286.       getch();                               /* is returned */
  287.       comm_putc('\20');                      /* send 'space' to modem to */
  288.       return(USR_BRK);                       /* cancel off-hook */
  289.     }
  290.     _bios_timeofday(_TIME_GETCLOCK,&get_tm); /* check Timeout counter */
  291.     }
  292.     while(get_tm <= end_tm && c_in_buf == 0) ;
  293.  
  294.     if(get_tm >= end_tm) return(TIMEOUT);        /* port timed out */
  295.  
  296.     ptr = outptr;
  297.     c = *ptr++;                                  /* Get next character in circular buff */
  298.     if ( ptr == &buffer[CBS] )                   /* Check for end of circular buffer */
  299.     {
  300.     ptr = buffer;                            /* start from bottom of buff */
  301.     }
  302.     _disable();                                  /* no interrupts during pointer manips */
  303.     outptr = ptr;                                /* set character output pointer */
  304.     c_in_buf--;                                  /* and decrement the character count */
  305.     _enable();                                   /* then allow interrupts to continue */
  306.     return(c);                                   /* Return the character */
  307. }
  308.  
  309. void comm_flush ( )                             /* flushes all chars out of buffer */
  310. {
  311.     if ( xofsnt )                               /* Check if XON needs to be sent */
  312.     {
  313.        xofsnt = 0;
  314.        comm_putc ( XON );
  315.     }
  316.     _disable ( );                                /* no interrupts during pointer manips */
  317.     inptr = outptr = buffer;                     /* reset buffer pointers */
  318.     c_in_buf = 0;                                /* and indicate no chars received */
  319.     _enable ( );
  320. }
  321.  
  322. void flsh_dtr ( )                                /* Drop DTR for 1/2 second */
  323. {
  324.     outp( com8250 + 1, 0xa);                     /* Un-set DTR (set RTS, OUT2) */
  325.     delay(500);                                  /* Wait for 1/2 second */
  326.     outp( com8250 + 1, 0xb);                     /* Set DTR, RTS, OUT2 */
  327.  
  328. }
  329.  
  330.  
  331. int carrier( )                                   /* TEST FOR CARRIER DETECT */
  332. {
  333.  
  334.   delay(200);                                    /* Short pause */
  335.   if((inp( MODEM_STAT ) & CARRIER_ON ) == CARRIER_ON)
  336.   {
  337.     return(1);                                   /* Check MSR for DCD */
  338.   }
  339.   return(0);
  340. }
  341.  
  342. void delay( int msecs)
  343. {
  344.  clock_t imsecs,goal;
  345.  imsecs=(clock_t)msecs*(CLOCKS_PER_SEC/1000);
  346.  goal=imsecs+clock();
  347.  while (goal >clock());
  348. }
  349.  
  350.  
  351. /****************************************************************************/
  352.  
  353. #ifdef DEBUG
  354.  
  355. #include <string.h>
  356.  
  357. main( int argc, char *argv[] )
  358. {
  359.    char result = 0;
  360.    int port = 1, speed = 9600;                   /* Default speed & port */
  361.    unsigned int ser_stat;
  362.    char c=0;
  363.  
  364.    if( argc >= 2 ) port = *argv[1] - 48;
  365.    if( argc == 3 ) speed = atoi( argv[2] );
  366.  
  367.    ser_stat=_bios_serialcom(_COM_INIT,0,
  368.                 _COM_9600|_COM_NOPARITY|_COM_CHR8);
  369.  
  370.    cprintf ( "\r\n"
  371.        "Serial port %d open at %d baud\r\n"
  372.        "test terminal for C comm isr's in power 1.X, turbo 1.X\r\n"
  373.        "hit \"ESC\" to exit\r\n\n", port, speed );
  374.    if ( comm_open ( port, speed ) ) 
  375.    {
  376.       while ( result != 27 && c != TIMEOUT) 
  377.       {
  378.      if ( kbhit() )                          /* Check for keyboard press */
  379.      {               
  380.         result = (char) getch();
  381.         if( result != 27 )  
  382.         {
  383.           comm_putc ( result );              /* If ! Escape */
  384.         }                                    /* Output the char */
  385.      }                                           
  386.      if(comm_avail()) 
  387.      {                                       /* Is a char waiting? */
  388.        c = (char) comm_getc(3);
  389.        switch ( c ) 
  390.        {
  391.          case '\t' :                         /* convert tabs */
  392.         for ( c = 0; c < 8; c++ )
  393.         putch ( ' ' );
  394.         break;
  395.          case TIMEOUT :                      /* check for timeout */
  396.         cprintf("\r\nPort Timed Out\r\n");  
  397.         break;                           /* error */
  398.          case '\r':
  399.         cprintf("%c%c",'\015','\012');
  400.         break;
  401.          default :
  402.         cprintf ("%c", c );              /* put char to screen */
  403.         break;
  404.        }                                     /* End of switch */
  405.      }                                       /* End of if (comm_avail()) */
  406.       }                                          /* End of while */
  407.  
  408.       cprintf("\nClosing Port %d\n",port);
  409.       comm_close();
  410.    }
  411.    else
  412.    {
  413.       cprintf ( "\r\nUnable to find port %d\r\n", port );
  414.    }
  415.    return ( 0 );
  416. }
  417.  
  418. #endif
  419.  
  420.